--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--
--	file:		gui_allu_res.lua
--	brief:	 Shows your allies resources and allows quick resource transfer
--	author:	Owen Martindell
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

function widget:GetInfo()
	return {
		name = "Ally Resource Bars",
		desc = "Shows your allies resources and allows quick resource transfer (v1.5)",
		author = "TheFatController & AF & BD",
		date = "July 2, 2010",
		license	= "MIT/x11",
		layer = -9,
		enabled	= true	--	loaded by default?
	}
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

local GetPlayerList = Spring.GetPlayerList
local GetPlayerInfo = Spring.GetPlayerInfo
local GetTeamResources = Spring.GetTeamResources
local GetMyTeamID = Spring.GetMyTeamID
local GetMouseState = Spring.GetMouseState
local GetSpectatingState = Spring.GetSpectatingState
local GetTeamColor = Spring.GetTeamColor
local IsReplay = Spring.IsReplay
local IsGUIHidden = Spring.IsGUIHidden
local ShareResources = Spring.ShareResources
local GetGameFrame = Spring.GetGameFrame
local GetAllyTeamList = Spring.GetAllyTeamList
local GetTeamList = Spring.GetTeamList
local GetTeamInfo = Spring.GetTeamInfo
local GetMyAllyTeamID = Spring.GetMyAllyTeamID
local GetAIInfo = Spring.GetAIInfo
local SendCommands = Spring.SendCommands
local mathMin = math.min
local sF = string.format
local glGetViewSizes = gl.GetViewSizes
local glDeleteList = gl.DeleteList
local glCreateList = gl.CreateList
local glRect = gl.Rect
local glColor = gl.Color
local glPushMatrix = gl.PushMatrix
local glCallList = gl.CallList
local glPopMatrix = gl.PopMatrix
local glPopAttrib = gl.PopAttrib

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

local displayList
local staticList
local BAR_HEIGHT = 5
local BAR_SPACER = 1
local BAR_WIDTH	= 100
local BAR_GAP = 3
local resourceTypes = { "metal", "energy" }
local TOTAL_BAR_HEIGHT = (BAR_SPACER + BAR_HEIGHT*#resourceTypes)
local TOP_HEIGHT = (BAR_GAP + BAR_GAP)
local BAR_OFFSET = (TOP_HEIGHT + BAR_SPACER)
local START_HEIGHT = (TOTAL_BAR_HEIGHT + BAR_GAP + TOP_HEIGHT)
local FULL_BAR = (BAR_WIDTH + BAR_GAP + BAR_GAP + BAR_SPACER)
local w	= (BAR_WIDTH + BAR_OFFSET + BAR_GAP)
local h = START_HEIGHT
local viewSizeX, viewSizeY = glGetViewSizes()
local x1 = - w + viewSizeX
local y1 = - h - 31 + viewSizeY
local sentSomething = false
local enabled = false
local transferring = false
local transferTeam
local transferType
local teamList = {}
local teamRes = {}
local teamIcons	= {}
local sendVector = {}
local sentVector = {}
local trnsVector = {}
for _, resourcename in ipairs(resourceTypes) do
	sendVector[resourcename] = {}
	sentVector[resourcename] = 0
	trnsVector[resourcename] = {}
end
local myID
local lastGameFrame = -1

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


local function setUpTeam()
	teamList = {}
	teamRes = {}
	myID = GetMyTeamID()
	mx, my = 0,0
	local spectator = GetSpectatingState()
	local alist = {GetMyAllyTeamID()}
	if spectator then
		alist = GetAllyTeamList()
	end
	for _,allyID in ipairs(alist) do
		local getTeams = GetTeamList(allyID)
		if getTeams ~= nil then
			for _,teamID in ipairs(getTeams) do
			 local _,_,isDead = GetTeamInfo( teamID )
			 if not isDead then
			 	if myID ~= teamID or spectator then
					teamList[teamID] = true
				end
			 end
			end
		end
	end
	enabled = (#teamList > 0)
	return enabled
end

function widget:Initialize()
	myID = GetMyTeamID()
	setUpTeam()
	enabled = enabled and GetGameFrame() > 0
end

function widget:Shutdown()
	glDeleteList(displayList)
end

local function updateStatics()
	if (staticList) then glDeleteList(staticList) end
	staticList = glCreateList( function()
		glColor(0, 0, 0.5, 0.2)
		glRect(x1, y1, x1+w,y1+h)
		local height = h - TOP_HEIGHT
		teamIcons = {}
		for teamID in pairs(teamList) do
			local _,teamLeader,_,isAI = GetTeamInfo( teamID )
			local playerName
			if not isAI then
				playerName = GetPlayerInfo(teamLeader)
			else
				_,_,playerName = GetAIInfo(teamID)
			end
			local r,g,b = GetTeamColor(teamID)
			if r and g and b then
				glColor(r,g,b)
			end
			glRect(x1+BAR_GAP,y1+height,x1+TOP_HEIGHT,y1+height-TOTAL_BAR_HEIGHT)
			teamIcons[teamID] =
			{
			 name = playerName or "No Player",
			 iy1 = y1+height,
			 iy2 = y1+height-TOTAL_BAR_HEIGHT,
			}
			height = (height - TOTAL_BAR_HEIGHT - BAR_GAP)
		end
	end)
end

local function updateBars()
	local height = h - TOP_HEIGHT
	for teamID in pairs(teamList) do
		teamRes[teamID] = {}
		for index,resname in ipairs(resourceTypes) do
			local Cur, Max = GetTeamResources(teamID, resname)
			Cur = Cur + (sendVector[resname][teamID] or 0)
			local resPercentage = Cur / Max
			local xoffset = (x1+BAR_OFFSET)
			barinfo = {
				x1	= xoffset,
				y1	= y1+height -(BAR_HEIGHT+BAR_SPACER)*(index-1),
				x2	= xoffset+BAR_WIDTH,
				x2b = xoffset+(BAR_WIDTH * (resPercentage)),
				y2	= y1+height -(BAR_HEIGHT)*(index) -BAR_SPACER*(index-1),
				Rec = (teamID == transferTeam)
			}
			teamRes[teamID][resname] = barinfo
		end
		height = (height - TOTAL_BAR_HEIGHT - BAR_GAP)
	end
	if (height ~= 0) then
		h = (h - height)
		y1 = (y1 + height)
		updateStatics()
	end
	if (displayList) then glDeleteList(displayList) end
	displayList = glCreateList( function()
		for _,d in pairs(teamRes) do
			for index,resname in ipairs(resourceTypes) do
				local barinfo = d[resname]
				if barinfo.Rec then
					glColor(0.8, 0, 0, 0.8)
				else
					glColor(0.8, 0.8, 0, 0.3)
				end
				glRect(barinfo.x1,barinfo.y1,barinfo.x2,barinfo.y2)
				if resname == "energy" then
					glColor(1, 1, 0, 1)
				elseif resname == "metal" then
					glColor(1, 1, 1, 1)
				else
					local percentage = (index/#resourceTypes)/2 + 0.5
					glColor(percentage, percentage, percentage, 1)
				end
				glRect(barinfo.x1,barinfo.y1,barinfo.x2b,barinfo.y2)
			end
		end
	end)
end

function widget:TeamDied(teamID)
	setUpTeam()
end


local function transferResources(n)
	local sCur, sMax = GetTeamResources(transferTeam, transferType)
	local lCur, _, _, lInc, _, _, _, lRec = GetTeamResources(myID, transferType)
	lCur = (lCur - sentVector[transferType])
	sCur = sCur + (sendVector[transferType][transferTeam] or 0)
	local send = mathMin(mathMin((sMax-sCur),((lInc+lRec)*0.2)),lCur)
	if (send > 0) then
		if sendVector[transferType][transferTeam] then
			sendVector[transferType][transferTeam] = (sendVector[transferType][transferTeam] + send)
		else
			sendVector[transferType][transferTeam] = send
			sentSomething = true
		end
		sentVector[transferType] = (sentVector[transferType] + send)
		trnsVector[transferType][transferTeam] = (send * 30)
	end
end

function widget:IsAbove(x,y)
	return (x > x1 + BAR_GAP) and (y > y1 + BAR_GAP) and (x < (x1 + FULL_BAR)) and (y < (y1 + h - TOP_HEIGHT))
end

function widget:GetTooltip(x,y)
	for teamID,defs in pairs(teamIcons) do
		if (y < defs.iy1) and (y >= defs.iy2) then
			local text = "\255\255\255\255" .. defs.name .. "\n"
			for _,resourcename in ipairs(resourceTypes) do
				local Cur, _, Pull, Inc, Exp, _, _, Rec = GetTeamResources(teamID, resourcename)
				Rec = Rec + (trnsVector[resourcename][teamID] or 0)
				if resourcename == "energy" then
					text = text .. " E: "
				elseif resourcename == "metal" then
					text = text .. " M: "
				else
					text = text .. " " .. resourcename .. ": "
				end
				local Net = Inc+Rec-Exp
				local NetReal = Inc+Rec-Pull
				if Net > 0 then
					text = text .. "\1\255\1\255 +"
				else
					text = text .. "\255\255\1\1"
				end
				text = text .. sF("%.1f",Net)
				if Net ~= NetReal then
		 			text = text .. sF("\255\255\1\1 (%.1f)",NetReal)
				end
				text = text .. "\255\255\255\255"
			end
			return text
		end
	end
end

function widget:GameStart()
	setUpTeam()
end

function widget:GameFrame(n)
		if not enabled then
			return
		end
	if transferTeam then
		transferResources(n)
	end
	if sentSomething and ((n % 16) == 0) then
		for _,resourcename in ipairs(resourceTypes) do
			for teamID,send in pairs(sendVector[resourcename]) do
				ShareResources(teamID,resourcename,send)
			end
			sendVector[resourcename] = {}
			sentVector[resourcename] = 0
			trnsVector[resourcename] = {}
		end
		sentSomething = false
		local x, y = GetMouseState()
		if (mx ~= x) or (my ~= y) or transferring or ((n % 15) == 0) then
		mx = x
		my = y
		end
	end
end

function widget:DrawScreen()
	local n = GetGameFrame()
	if enabled and lastGameFrame ~= n then
		updateBars()
	end
	lastgGameFrame = n
	if enabled and (not IsGUIHidden()) then
		glPushMatrix()
			glCallList(staticList)
			glCallList(displayList)
		glPopMatrix()
	end
end

function widget:TweakMouseMove(x, y, dx, dy, button)
	if (enabled) then
		if capture then
			x1 = x1 + dx
			y1 = y1 + dy
			updateBars()
			updateStatics()
		end
	end
end

function widget:MouseMove(x, y, dx, dy, button)
	if (enabled) then
		if transferring then
			transferTeam = nil
			if (x > (x1+BAR_OFFSET)) and (x < (x1+BAR_OFFSET+BAR_WIDTH)) then
				for teamID,defs in pairs(teamRes) do
					local barinfo = defs[trasfertype]
					if (y < barinfo.y1) and (y > barinfoy2) then
						transferTeam = teamID
						return
					end
				end
			end
		end
	end
end

function widget:TweakMousePress(x, y, button)
	if button ~= 1 then
		return false
	end
	if (enabled) and ((x > x1) and (y > y1) and (x < (x1 + w)) and (y < (y1 + h))) then
		capture = true
		return true
	end
	return false
end

function widget:TweakMouseRelease(x, y, button )
	capture = nil
end

function widget:MousePress(x, y, button)
	if (enabled) and ((x > x1) and (y > y1) and (x < (x1 + w)) and (y < (y1 + h))) then
		if (x > (x1+BAR_OFFSET)) and (x < (x1+BAR_OFFSET+BAR_WIDTH)) then
			for teamID,defs in pairs(teamRes) do
				for _,resname in ipairs(resourceTypes) do
					local barinfo = defs[resname]
					if (y < barinfo.y1) and (y >= barinfo.y2) then
						if GetSpectatingState() or IsReplay() then
							SendCommands('specteam '..teamID)
						else
							transferTeam = teamID
							transferType = resname
							transferring = true
						end
						return true
					end
				end
			end
		end
	end
	return false
end

function widget:MouseRelease(x, y, button)
	transferring = false
	transferTeam = nil
	return capture
end

function widget:ViewResize(vsx, vsy)
	x1 = x1 * vsx / viewSizeX
	y1 = y1 * vsy / viewSizeY
	viewSizeX = vsx
	viewSizeY = vsy
	updateBars()
	updateStatics()
end

function widget:GetConfigData(data)
	return {
		x = x1,
		y = y1,
	}
end

function widget:SetConfigData(data)
	x1 = data.x or x1
	y1 = data.y or y1
	local viewX, viewY = glGetViewSizes()
	x1 = math.min( x1, viewX - w )
	y1 = math.min( y1, viewY - h )
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
